package com.inspur.edp.bff.core.manager;

import com.inspur.edp.cef.api.response.viewrule.ViewRule;
import com.inspur.edp.cef.api.response.viewrule.ViewRuleButtonConfig;
import com.inspur.edp.cef.api.response.viewrule.ViewRuleFieldConfig;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.ObjectType;
import com.inspur.edp.wf.bizprocess.entity.ButtonState;
import com.inspur.edp.wf.bizprocess.entity.FieldState;
import com.inspur.edp.wf.bizprocess.entity.FormButtonConfig;
import com.inspur.edp.wf.bizprocess.entity.FormFieldConfig;
import com.inspur.edp.wf.bizprocess.entity.FormFormatConfig;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;

/**
 * ViewRule工具类
 *
 * @author Kaixuan Shi
 * @since 2024/3/9
 */
class ViewRuleUtil {

    private static final String SPLIT_PATTERN_IN_RESULT = ".[*].";
    private static final String SPLIT_PATTERN_IN_DATA_CHANGE = ".[*].ChangeInfo.";

    /**
     * 将wf的按钮配置、附件的配置转为bff的ViewRule
     *
     * @param wfFormFormatConfig wf的字段、按钮配置结果
     * @return bff的权限配置结果
     */
    @Nonnull
    public static ViewRule getViewRule(@Nullable FormFormatConfig wfFormFormatConfig) {
        ViewRule viewRule = new ViewRule();
        if (wfFormFormatConfig == null) {
            return viewRule;
        }
        //1、将wf按钮配置转为vo的按钮配置结果集
        List<FormButtonConfig> formButtonConfigs = wfFormFormatConfig.getFormButtonConfigs();
        if (formButtonConfigs != null && !formButtonConfigs.isEmpty()) {
            viewRule.setButtonConfigs(new ArrayList<>(formButtonConfigs.size()));
            formButtonConfigs.forEach((formButtonConfig -> {
                if (formButtonConfig != null) {
                    ViewRuleButtonConfig buttonConfig = getButtonConfig(formButtonConfig);
                    viewRule.getButtonConfigs().add(buttonConfig);
                }
            }));
        }
        //2、将wf字段配置转为vo的字段配置结果集
        List<FormFieldConfig> formFieldConfigs = wfFormFormatConfig.getFormFieldConfigs();
        if (formFieldConfigs != null && !formFieldConfigs.isEmpty()) {
            viewRule.setFieldConfigs(new ArrayList<>(formFieldConfigs.size()));
            formFieldConfigs.forEach((formFieldConfig -> {
                if (formFieldConfig != null) {
                    ViewRuleFieldConfig fieldConfig = getFieldConfig(formFieldConfig);
                    viewRule.getFieldConfigs().add(fieldConfig);
                }
            }));
        }
        return viewRule;
    }

    /**
     * 判断字段是否隐藏
     *
     * @param viewRuleFieldConfig 字段配置
     * @return true: 隐藏 false: 不隐藏
     */
    public static boolean isHidden(@Nonnull ViewRuleFieldConfig viewRuleFieldConfig) {
        return viewRuleFieldConfig.getConfigOfInt() == 0x0000;
    }

    /**
     * 判断字段是否不可更改
     *
     * @param viewRuleFieldConfig 字段配置
     * @return true: 不可更改 false: 可更改
     */
    public static boolean isUnchangeable(@Nonnull ViewRuleFieldConfig viewRuleFieldConfig) {
        // 设置为不可见与不可编辑的字段，都属于不可更改的字段
        return (viewRuleFieldConfig.getConfigOfInt() & 0x0001) == 0x0000
                || (viewRuleFieldConfig.getConfigOfInt() & 0x0010) == 0x0000;
    }

    /**
     * 构造字段在返回结果中的JsonPath
     */
    public static String buildJsonPathInResult(@Nonnull ViewRuleFieldConfig fieldConfig) {
        StringBuilder stringBuilder = new StringBuilder();

        if (!StringUtils.isBlank(fieldConfig.getNodeCode())) {
            stringBuilder
                    .append(fieldConfig.getNodeCode().replace(".", SPLIT_PATTERN_IN_RESULT))
                    .append(SPLIT_PATTERN_IN_RESULT);
        }
        stringBuilder.append(fieldConfig.getId());
        return stringBuilder.toString();
    }

    /**
     * 构造字段在变更集中的JsonPath
     */
    public static String buildJsonPathInDataChange(@Nonnull ViewRuleFieldConfig fieldConfig, @Nonnull ObjectType objectType) {
        StringBuilder stringBuilder = new StringBuilder("ChangeInfo.");

        if (!StringUtils.isBlank(fieldConfig.getNodeCode())) {
            stringBuilder
                    .append(fieldConfig.getNodeCode().replace(".", SPLIT_PATTERN_IN_DATA_CHANGE))
                    .append(SPLIT_PATTERN_IN_DATA_CHANGE);
        }
        switch (objectType) {
            case UDT:
                // UDT类型的在变更集中的字段定位，要添加一段
                String fieldId = fieldConfig.getId();
                int index = fieldId.indexOf(".");
                if (index == -1) {
                    stringBuilder.append(fieldId);
                } else {
                    stringBuilder.append(fieldId, 0, index)
                            .append(".ChangeInfo.")
                            .append(fieldId.substring(index + 1));
                }
                break;
            case Association:
                // 关联类型，id中包含带出字段（如refField.name），应该是整个字段refField不可修改
                stringBuilder.append(fieldConfig.getId().split("\\.")[0]);
                break;
            case DynamicProp:
            case Enum:
            case Normal:
                stringBuilder.append(fieldConfig.getId());
                break;
            default:
                throw new IllegalArgumentException("Unsupported ObjectType: " + objectType);
        }
        return stringBuilder.toString();
    }

    @Nonnull
    private static ViewRuleButtonConfig getButtonConfig(@Nonnull FormButtonConfig formButtonConfig) {
        ViewRuleButtonConfig buttonConfig = new ViewRuleButtonConfig();
        buttonConfig.setId(formButtonConfig.getButtonId());
        buttonConfig.setConfig(getButtonConfigIntValue(formButtonConfig.getButtonState()));
        return buttonConfig;
    }

    @Nonnull
    private static ViewRuleFieldConfig getFieldConfig(@Nonnull FormFieldConfig wfFormFieldConfig) {
        ViewRuleFieldConfig fieldConfig = new ViewRuleFieldConfig();
        //子表字段的id在wf中是“子表编号#子子表编号#字段编号”,需拆分
        String wfField = wfFormFieldConfig.getFieldId();
        int lastIndex = wfField.lastIndexOf("#");
        if (lastIndex == -1) {
            fieldConfig.setId(wfField);
        } else {
            fieldConfig.setId(wfField.substring(lastIndex + 1));
            fieldConfig.setNodeCode(wfField.substring(0, lastIndex).replace("#", "."));
        }
        fieldConfig.setConfig(getFiledConfigIntValue(wfFormFieldConfig.getFieldState()));
        return fieldConfig;
    }

    private static int getFiledConfigIntValue(FieldState fieldState) {
        if (fieldState == null) {
            throw new IllegalArgumentException("fieldState is null");
        }
        switch (fieldState) {
            case Hidden:
                return 0x0000;
            case Editable:
                return 0x0011;
            case Readonly:
                return 0x0001;
            case Required:
                return 0x0111;
            default:
                throw new IllegalArgumentException(fieldState.toString());
        }
    }

    private static int getButtonConfigIntValue(ButtonState buttonState) {
        if (buttonState == null) {
            throw new IllegalArgumentException("buttonState is null");
        }
        switch (buttonState) {
            case Disabled:
                return 0x01;
            case Enable:
                return 0x11;
            case Hidden:
                return 0x00;
            default:
                throw new IllegalArgumentException(buttonState.toString());
        }
    }
}
